package cn.ztydata.teachingsystem.heaven.service;


import cn.ztydata.teachingsystem.common.Page;
import cn.ztydata.teachingsystem.exception.ServiceException;
import cn.ztydata.teachingsystem.heaven.common.WebContext;
import cn.ztydata.teachingsystem.heaven.cons.Constants;
import cn.ztydata.teachingsystem.heaven.cons.GroupType;
import cn.ztydata.teachingsystem.heaven.cons.Roles;
import cn.ztydata.teachingsystem.heaven.dao.*;
import cn.ztydata.teachingsystem.heaven.entity.*;
import cn.ztydata.teachingsystem.heaven.entity.Class;
import cn.ztydata.teachingsystem.heaven.exception.ExcelException;
import cn.ztydata.teachingsystem.util.ExcelUtil;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.io.InputStream;
import java.util.*;


/**
 * 课程群组业务类
 * Created by wyh on 2015/3/26.
 */
@Service

public class CourseGroupService extends BaseService {
    @Autowired
    private HcourseGroupDao hcourseGroupDao;
    @Autowired
    private HistoryScDao historyScDao;
    @Autowired
    private StudentCourseDao studentCourseDao;
    @Autowired
    private TeacherDao teacherDao;
    @Autowired
    private DepartmentDao departmentDao;
    @Autowired
    private CourseGroupDao courseGroupDao;
    @Autowired
    private CourseService courseService;
    @Autowired
    private CourseDao courseDao;
    @Autowired
    private WebContext webContext;
    @Autowired
    private ClassGroupDao classGroupDao;
    @Autowired
    private SpecialtyGroupService specialtyGroupService;



    //<editor-fold "课程群组">
    /**
     * 获取当前课程群组
     *
     * @param pageNum  当前页码
     * @param pageSize 每页条数
     * @return Page<CourseGroup>
     * @author lyj
     * @since 2015-3-31
     */
    public Page<CourseGroup> getSemester(final int pageNum, final int pageSize, final String keyWord) {

        if (webContext.getRole() != Roles.TEACHER && webContext.getRole() != Roles.STUDENT) {
            throw new ServiceException("权限错误！");
        }

        //判断角色
        int role = (webContext.getRole() == Roles.STUDENT ? 1 : 0);

        Page<CourseGroup> page = courseGroupDao.getSemester(pageNum, pageSize, keyWord, role);

        if (page.getItems().size() == 0) {
            log.debug("获取当前课程群组page.getItems().size() == 0");
            return new Page<>();
        }

        Set<String> courseCodes = new HashSet<>(); //存储课程代码

        //循环读取课程代码
        log.debug("循环读取课程代码");
        for (CourseGroup courseGroup : page.getItems()) {
            courseCodes.add(courseGroup.getCode());
        }

        //根据课程代码获取课程ID、课程名称
        Map<String, Map<String, Object>> maps = courseService.getIdName(courseCodes);

        //绑定课程名称、课程ID
        log.debug("绑定课程名称、课程ID");
        for (CourseGroup courseGroup : page.getItems()) {
            Map<String, Object> reMap = maps.get(courseGroup.getCode()); //获取课程名称、课程ID
            if (reMap != null) {
                log.debug("reMap != null");
                courseGroup.setCourseId(Long.parseLong(reMap.get("courseId").toString()));
                courseGroup.setCourseName(reMap.get("courseName").toString());
            }
        }

        log.debug("获取当前课程群组");
        return page;
    }


    /**
     * 获取历史课程群组列表
     *
     * @param startYear 开始学年
     * @param term      学期
     * @param pageNum   当前页码
     * @param pageSize  每页条数
     * @return Page<CourseGroup>
     * @author lyj
     * @since 2015-3-31
     */
    public Page<CourseGroup> getHistory(final String startYear, final int term, final int pageNum, final int pageSize, final String keyWord) {
        if (webContext.getRole() != Roles.TEACHER && webContext.getRole() != Roles.STUDENT) {
            throw new ServiceException("权限错误！");
        }
        //判断角色
        int role = (webContext.getRole() == Roles.STUDENT ? 1 : 0);

        Page<CourseGroup> page = courseGroupDao.getHistory(startYear, term, pageNum, pageSize, keyWord, role);

        if (page.getItems().size() == 0) {
            log.debug("page.getItems().size() == 0");
            return new Page<>();
        }

        Set<String> courseCodes = new HashSet<>(); //存储课程代码

        //循环读取课程代码
        log.debug("循环读取课程代码");
        for (CourseGroup courseGroup : page.getItems()) {
            courseCodes.add(courseGroup.getCode());
        }

        //根据课程代码获取课程ID、课程名称
        Map<String, Map<String, Object>> maps = courseService.getIdName(courseCodes);

        //绑定课程名称、课程ID
        log.debug("绑定课程名称、课程ID");
        for (CourseGroup courseGroup : page.getItems()) {
            Map<String, Object> reMap = maps.get(courseGroup.getCode()); //获取课程名称、课程ID
            if (reMap != null) {
                log.debug("reMap != null");
                courseGroup.setCourseId(Long.parseLong(reMap.get("courseId").toString()));
                courseGroup.setCourseName(reMap.get("courseName").toString());
            }
        }

        log.debug("获取历史课程群组列表");
        return page;
    }


    /**
     * 根据课程ID获取课程明细
     *
     * @param courseId 课程ID
     * @param groupId  群组ID
     * @return Course
     * @author lyj
     * @since 2015-3-31
     */
    public Course getDetail(final long courseId, final long groupId, final int type, final User userInfo) {
        if (webContext.getRole() != Roles.TEACHER && webContext.getRole() != Roles.STUDENT) {
            throw new ServiceException("权限错误！");
        }

        //判断登录用户是否可以获取该课程群组信息
        if (courseGroupDao.checkGroupIdIsNum(groupId, userInfo.getNumber()) == 0) {
            throw new ServiceException("权限错误！");
        }

        //获取课程明细
        Course course = courseDao.getDetail(courseId);

        if (course == null) {
            log.debug("course == null");
            return course;
        }

        //获取课程群组负责人头像、姓名
        Teacher teacher = new Teacher();
        if (type == 0) {
            teacher = courseGroupDao.getLeaderId(groupId);
        } else {
            hcourseGroupDao.getLeaderId(groupId);
        }

        if (teacher != null) {
            log.debug("teacher != null");
            //绑定头像姓名
            course.setLeaderPhoto(teacher.getPicture());
            course.setGroupLeader(teacher.getName());
        }


        //获取课程群组明细
        CourseGroup courseGroup = new CourseGroup();
        if (type == 0) {
            courseGroup = courseGroupDao.getById(groupId);
        } else {
            courseGroup = hcourseGroupDao.getById(groupId);
        }

        if (courseGroup != null) {
            log.debug("courseGroup != null");
            course.setLessonCode(courseGroup.getCode());
            course.setGroupName(courseGroup.getName());
        }

        log.debug("根据课程ID获取课程明细");
        return course;
    }


    /**
     * 获取历史学期下拉列表
     *
     * @return List
     * @author lyj
     * @since 2015-3-31
     */
    public List<Integer> getStartYear(final String userNum) {
        log.debug("获取历史学期下拉列表");
        return courseGroupDao.getStartYear(userNum);
    }


    /**
     * 获取课程群组的负责人
     *
     * @param groupId 课程群组编号
     * @return String
     * @author fanruiping
     * @since 2015-04-02
     */

    public String getTeacherNameById(Long groupId) {
        return teacherDao.getNameByCourseGroup(groupId);
    }


    /**
     * 为教师或学生获取课程群组下拉框
     *
     * @param type 获取类型（0：教师，1：学生）
     * @param user 用户信息
     * @return List
     * @author fanruiping
     * @since 2015-04-06
     */
    public List<CourseGroup> getForTeacherAndStudent(int type, User user) {
        List<CourseGroup> courseGroups = new ArrayList<>();

        //角色为教师且登录用户角色为超级管理员
        if (type == 0 && user.getRole() == Roles.SUPER_ADMIN) {
            log.debug("获取数据类型为教师且登录用户为超级管理员:type == 0 && user.getRole() == Roles.SUPER_ADMIN");

            courseGroups = courseGroupDao.getAll();
        } else if (type == 0 && user.getRole() != Roles.STUDENT) {
            log.debug("获取数据类型为教师且登录角色不为学生:type == 0 && user.getRole() != Roles.STUDENT");

            courseGroups = courseGroupDao.getListForTeacher(user.getNumber());
        } else if (type == 1 && user.getRole() == Roles.STUDENT) {
            log.debug("获取数据类型为学生且登录角色为学生:type == 0 && user.getRole() == Roles.STUDENT");

            courseGroups = courseGroupDao.getListForStudent(user.getNumber());
        }

        //判断课程群组集合是否为空
        if (!courseGroups.isEmpty()) {
            log.debug("课程群组集合不为空:!courseGroups.isEmpty()");

            List<String> codes = new ArrayList<>();

            log.debug("循环课程群组集合获取群组代码:CourseGroup courseGroup : courseGroups");
            //循环获取课程代码
            for (CourseGroup courseGroup : courseGroups) {
                codes.add(courseGroup.getCode());
            }

            //根据课程代码获取课程信息
            Map<String, Course> courseMap = this.getByCodes(codes);

            log.debug("循环课程群组集合插入群组编号和专业编号:CourseGroup courseGroup : courseGroups");
            //循环插入课程编号和专业编号
            for (CourseGroup courseGroup : courseGroups) {
                //判断课程群组集合中是否包含指定群组代码的数据
                if (null != courseMap && courseMap.containsKey(courseGroup.getCode())) {
                    log.debug("课程群组集合中包含指定群组代码的数据");

                    courseGroup.setCourseId(courseMap.get(courseGroup.getCode()).getId());
                    courseGroup.setSpecialtyId(courseMap.get(courseGroup.getCode()).getSpecId());
                }
            }
        }

        return courseGroups;
    }

    /**
     * 获取课程map数据
     *
     * @param codes 课程代码
     * @return Map
     * @author fanruiping
     * @since 2015-04-06
     */
    private Map<String, Course> getByCodes(List<String> codes) {
        List<Map<String, Course>> courseMap = courseDao.getMapByCodes(codes);

        Map<String, Course> result = new HashMap<>();
        for (Map<String, Course> course : courseMap) {
            result.putAll(course);
        }
        return result;
    }

    /**
     * 读取Excel文件 课程群组
     *
     * @param in 文件输入流
     * @author wyh
     * @since 2015/3/26
     */
    public List<CourseGroup> readFromExcel(InputStream in) throws IOException {
        //定义标题-属性的映射
        LinkedHashMap<String, String> fieldMap = Maps.newLinkedHashMap();
        fieldMap.put("课程代码", "code");
        fieldMap.put("课程群组名称", "name");
        fieldMap.put("系部编码", "deptNum");
        fieldMap.put("负责教师工号", "teacherNum");

        log.debug("转换Excel课程群组信息为List");
        return ExcelUtil.excelToList(in, CourseGroup.class, fieldMap);
    }

    /**
     * 检查导入课程群组数据中的课程代码冲突
     *
     * @param courseGroupList 课程群组集合
     * @author wyh
     * @since 2015-03-26
     */
    public void checkForCode(final List<CourseGroup> courseGroupList) {
        //判断条数
        if (courseGroupList.size() > Constants.TOTAL_2K) {
            log.debug("导入数据量超过" + Constants.TOTAL_2K);
            throw new ExcelException("导入数据量超过" + Constants.TOTAL_2K);
        }

        //抽取课程代码集合
        Set<String> courseGroupCodeSet = Sets.newHashSet();
        int index = 1;
        log.debug("循环导入的课程群组集合");
        for (CourseGroup courseGroup : courseGroupList) {
            if (courseGroup.getCode() == null) {
                log.debug("课程代码 is null");

                throw new ExcelException("导入数据中第" + index + "条数据课程代码为空");
            }

            //检查导入数据中是否存在重复课程代码
            if (courseGroupCodeSet.contains(courseGroup.getCode())) {
                log.debug("导入数据中的课程代码重复");

                throw new ExcelException("导入数据中第" + index + "条数据的课程代码重复");
            }

            courseGroupCodeSet.add(courseGroup.getCode());
            index++;
        }

        //检查导入数据课程代码是否与数据库中记录冲突
        String duplicateNum = courseGroupDao.getDuplicateCode(courseGroupCodeSet);

        if (duplicateNum != null) {
            log.debug("数据库中存在导入的课程代码");

            throw new ExcelException("课程代码为:" + duplicateNum + "的课程群组已经存在");
        }

        //检查导入课程代码是否与归档的记录冲突
        duplicateNum = hcourseGroupDao.getDuplicateCode(courseGroupCodeSet);
        courseGroupCodeSet.clear();
        if (duplicateNum != null) {
            log.debug("数据库中存在导入的课程代码");

            throw new ExcelException("课程代码为:" + duplicateNum + "的课程群组已经存在");
        }
    }

    /**
     * 批量新增课程群组
     *
     * @param courseGroupList 课程群组集合
     * @author wyh
     * @since 2015-03-26
     */
    @Transactional
    public void saveCourseGroups(final List<CourseGroup> courseGroupList) {
        try {
            //执行批量插入
            courseGroupDao.saveCourseGroups(courseGroupList);
        } catch (DataAccessException ex) {
            log.debug("导入课程群组-批量新增异常");

            log.warn("导入课程群组-批量新增异常", ex);
            throw new ExcelException();
        }
    }

    /**
     * 课程群组归档
     *
     * @author wyh
     * @since 2015-03-27
     */
    @Transactional
    public void historyCourseGroups() {
        hcourseGroupDao.saveAll();
        courseGroupDao.deleteAll();
        historyScDao.saveAll();
        studentCourseDao.deleteAll();
    }

    /**
     * 课程群组列表
     *
     * @param depart   系部编码
     * @param page     页码
     * @param pageSize 页数
     * @return Page
     * @author wyh
     * @since 2015-03-30
     */
    public Page<CourseGroup> listGroup(String depart, int page, int pageSize) {
        log.debug("返回 当前课程群组列表");
        return courseGroupDao.listGroup(depart, page, pageSize);
    }

    /**
     * 历史课程群组列表
     *
     * @param depart    系部编码
     * @param startYear 起始学年
     * @param term      学期
     * @param page      页码
     * @param pageSize  页数
     * @return Page
     * @author wyh
     * @since 2015-03-30
     */
    public Page<CourseGroup> listHistoryGroup(String depart, String startYear, int term, int page, int pageSize) {

        //保存系部编码和教师号
        List<String> teacherNumList = new ArrayList<>();
        List<String> departCodeList = new ArrayList<>();

        Page<CourseGroup> groupPage = hcourseGroupDao.listHistoryGroup(depart, startYear, term, page, pageSize, teacherNumList, departCodeList);

        //查询教师姓名
        Map<String,String> teacherList = new HashMap<>();
        if (!teacherNumList.isEmpty()) {
            log.debug("教师工号集合不为空：!teacherNumList.isEmpty()");
            teacherList = teacherDao.getNameByNums(teacherNumList);
        }

        //查询系部名
        Map<String,String> departmentList = new HashMap<>();
        if (!departCodeList.isEmpty()) {
            log.debug("系部编码集合不为空：!departCodeList.isEmpty()");
            departmentList = departmentDao.getNamesByNumbers(departCodeList);
        }

        log.debug("循环set教师姓名和系部名称");
        for (CourseGroup group : groupPage.getItems()) {
            //插入教师名称
            group.setTeacher(teacherList.get(group.getTeacherNum()));

            //插入系部名称
            group.setDepart(departmentList.get(group.getDeptNum()));
        }

        log.debug("返回 历史课程群组列表");
        return groupPage;
    }


    /**
     * 获取登录人是否可以获取指定群组的信息
     * @param groupId
     * @param groupType
     * @param userInfo
     * @return list
     * @author lyj
     * @since 2015-4-23
     */
    public Boolean getAllGroupIds(final long groupId, final int groupType, final User userInfo) {
        //验证课程群组权限
        if (groupType == GroupType.COURSE_GROUP ) {
            //判断登录用户是否可以获取该课程群组信息
            if (courseGroupDao.checkGroupIdIsNum(groupId, userInfo.getNumber()) == 0) {
                return false;
            }

        } else if (groupType == GroupType.CLASS_GROUP) { //验证班级群组权限
            //判断登录用户是否可以获取该班级群组信息
            if (classGroupDao.checkGroupIdIsNum(groupId, userInfo.getNumber()) == 0) {
                return false;
            }

        } else if (groupType == GroupType.SPEC_GROUP) { //验证专业群组权限
            //判断登录用户是否可以获取该专业群组信息
            if (!specialtyGroupService.getSpecialtyIds(userInfo).contains(groupId)) {
                return false;
            }
        }

        return true;
    }
    //</editor-fold>



}
